package framework;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.TimeZone;

import org.apache.commons.io.FileUtils;

/** Класс содержит набор общих функций
 */
public class CommonFunctions {

	private static Logger logger = Logger.getInstance();
	private static Boolean serFilesIsCopied = false;
	private static final int MAX_RAND = 8;
	private static final int MAX_RAND_STR = 11;
	private static final int MAX_DEVIATION = 6;
	/** Копирует файлы сериализации полученные как артифакты
	 * вышестоящего проекта в workspace. Путь к этим артифактам:  workspace/target/*.ser
	 */
	@SuppressWarnings("static-access")
	public static void copySerializationFiles(){

		FileUtils fileUtils = new FileUtils();
		if(!serFilesIsCopied){
			try{
		          File f1 = new File("./target/");
		          if(!f1.exists()){
		        	  f1 = new File("../target/");
		        	 if(!f1.exists()){
		        		 System.out.println("ОТСУТСТВУЮТ ФАЙЛЫ СЕРИАЛИЗАЦИИ ИЗ ВЫШЕСТОЯЩИХ ПРОЕКТОВ");
		        		 return;
		        	 }
		          }
		          f1 = new File(f1.getAbsolutePath());
		          File f2 = new File("./");
		          fileUtils.copyDirectory(f1, f2);

		         /* InputStream in = new FileInputStream(f1);

		          //For Overwrite the file.
		          OutputStream out = new FileOutputStream(f2);

		          byte[] buf = new byte[Integer.parseInt("1024")];
		          int len;
		          while ((len = in.read(buf)) > 0){
		            out.write(buf, 0, len);
		          }
		          in.close();
		          out.close();*/
		          System.out.println("ФАЙЛЫ СЕРИАЛИЗАЦИИ ИЗ ПРЕДЫДУЩЕГО ПРОЕКТА СКОПИРОВАНЫ");
		          serFilesIsCopied = true;
		        }catch(FileNotFoundException ex){
		          System.out.println(ex.getMessage() + " in the specified directory.");
		          System.exit(0);
		        }catch(IOException e){
		          System.out.println(e.getMessage());
		        }
		}
		serFilesIsCopied = true;
	}

	/** Возвращает нужную дату в заданном формате
	 * @param dateFormat формат даты
	 * @param addDay количество дней вперед, начиная от текущей даты
	 * @return дата в нужном формате
	 */
	public static String getDate(String dateFormat, int addDay){
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.DATE, addDay);
		Date date = (Date) calendar.getTime();
		SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
		formatter.setTimeZone(TimeZone.getTimeZone("Etc/GMT-4"));
		return  formatter.format(date);
	}

	/** Преобразовывает дату в нужный формат
	 * @param date дата
	 * @param oldFormat старый формат
	 * @param newFormat новый формат
	 * @return дата в нужном формате
	 */
	public static String convertDate(String date, String oldFormat, String newFormat){
		SimpleDateFormat df = new SimpleDateFormat(oldFormat);
        Date d = null;
		try {
			d = df.parse(date);
		} catch (ParseException e) {
			logger.info("Переданная дата " + date + " не в нужном формате: " + oldFormat);
			e.printStackTrace();
		}
        Calendar cal = Calendar.getInstance();
        cal.setTime(d);
        df = new SimpleDateFormat(newFormat);
        return df.format(cal.getTime());
	}

	/** Возвращает массив времени, с минутным отклонением в разные стороны
	 * @param time время
	 * @param deviation отклонение в одну сторону
	 * @return массив времени
	 */
	public static String[] getTimesArray(String time, int deviation){
		int timesArrayLength = deviation * 2;
		String[] times = new String[timesArrayLength];
		for(int i = -(timesArrayLength/2 - 1); i <= timesArrayLength/2; i++){
			try{
				SimpleDateFormat df = new SimpleDateFormat("HH:mm");
		        Date d = df.parse(time);
		        Calendar cal = Calendar.getInstance();
		        cal.setTime(d);
		        cal.add(Calendar.MINUTE, i);
		        d = cal.getTime();
		        times[i + (timesArrayLength/2 - 1)] = df.format(d);
		    }catch(ParseException e){
				logger.info(e.getMessage());
			}
		}
		return times;
	}

	/** Возвращает массив времени, с минутным отклонением в разные стороны(отклонение равно 6)
	 * @param time время
	 * @return массив времени
	 */
	public static String[] getTimesArray(String time){
		return getTimesArray(time, MAX_DEVIATION);
	}

	/** Разбивает число больше 1000 в группы по три через пробел,
	 * например если на входе '3300', то на выходе будет '3 300'
	 * @param number разбиваемое число
	 * @return разбитое число
	 */
	public static String convertNumberToFormat(String number){
		String mNumber = "";
		String invertNumber = "";
		String fractionalPart = "";
		String fractionalDivider = "";
		// Если число содержит точку или запятую, то обрезаем его до точки
		if(number.contains(".")||number.contains(",")){
			if(number.contains(".")){
				fractionalDivider = ".";
			}else if(number.contains(",")){
				fractionalDivider = ",";
			}
			fractionalPart = number.substring(number.indexOf(fractionalDivider) + 1);
			number = number.substring(0, number.indexOf(fractionalDivider));
		}
		// Если количество символов больше трех, то делаем разбивку по три символа через пробел
		if(number.length() > 2 + 1){
			// Получаем инвертированное число
			for(int i = number.length() - 1; i >= 0; i--){
				invertNumber = invertNumber + number.substring(i, i + 1);
			}
			// Разбиваем число
			for(int i = 0; i < invertNumber.length(); i++){
				if((i + 1) % (2 + 1) == 0){
					mNumber = mNumber + invertNumber.substring(i,i + 1) + " ";
				}else{
					mNumber = mNumber + invertNumber.substring(i,i + 1);
				}
			}
			// Делаем обратную инверсию числа
			number = "";
			for(int i = mNumber.length() - 1; i >= 0; i--){
				number = number + mNumber.substring(i,i+1);
			}
		}
		// Работа с дробной частью:
		// Если один знак после точки/запятой, то добавляем 0
		// Иначе оставляем как есть
		if(fractionalPart.length() < 1){
			fractionalPart = "00";
		}else if(fractionalPart.length() < 2){
			fractionalPart = fractionalPart + "0";
		}
		return number + "," + fractionalPart;
	}

	/**
	 * Получить полный путь к файлу, если существует
	 * @param path имя
	 * @return полный путь
	 */
	public static String getPathOfFile(String path) {
		File file = new File("." + path);
		if(!file.exists()) {
			file = new File(".." + path);
		}
		try {
			return file.getCanonicalPath();
		} catch (IOException e) {
			return "";
		}
	}

	/** Возвращает случайное значение определенной длинны
	 * @param length необходимая длина числа
	 * @return случайное значение нужной длины
	 */
	public static String getRandomValue(int length){
		Random r = new Random();
		String value = "";
		for(int i = 0; i < length; i++){
			value = value + String.valueOf(r.nextInt(MAX_RAND) + 1);
		}
		return value;
	}

	private static String[] words = {"Авто ","генерируемый ", "Текст ", "Белые ",
			"медведи ", "ходят,", "едят ", "полярников,", "Экспедиция ", "успешна ", "мороз ", "кушать "};
	/** Возвращает случайное значение определенной длинны (Строка)
	 * @param length необходимая длина числа
	 * @return случайное значение нужной длины
	 */
	public static String getRandomStringValue(int length){
		Random r = new Random();
		String value = "";
		for(int i = 0; i < length/5; i++){
			value = value + words[r.nextInt(MAX_RAND_STR)];
		}
		value = value.substring(0, length-2) + ".";
		return value;
	}

	/** Возвращает текущую дату в формате dd.MM.yyyy
	 * @return дата в формате dd.MM.yyyy
	 */
	public static String getCurrentDate(){
		return getDate("dd.MM.yyyy", 0);
	}

	/** Возвращает текущее время в формате HH:mm
	 * @return текущее время в формате HH:mm
	 */
	public static String getCurrentTime(){
		return getDate("HH:mm", 0);
	}
}
